home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / domacnost a kancelar / joomla / Joomla_1.5.4-Stable-Full_Package.exe / libraries / phpgacl / gacl.php < prev    next >
PHP Script  |  2008-07-06  |  20KB  |  627 lines

  1. <?php
  2. // $Id: gacl.php 10381 2008-06-01 03:35:53Z pasamio $
  3.  
  4. /**
  5.  * phpGACL - Generic Access Control List
  6.  * Copyright (C) 2002,2003 Mike Benoit
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with this library; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21.  *
  22.  * For questions, help, comments, discussion, etc., please join the
  23.  * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
  24.  *
  25.  * You may contact the author of phpGACL by e-mail at:
  26.  * ipso@snappymail.ca
  27.  *
  28.  * The latest version of phpGACL can be obtained from:
  29.  * http://phpgacl.sourceforge.net/
  30.  *
  31.  * @package phpGACL
  32.  */
  33.  
  34. /*
  35.  * Path to ADODB.
  36.  */
  37. //if ( !defined('ADODB_DIR') ) {
  38. //    define('ADODB_DIR', dirname(__FILE__).'/adodb');
  39. //}
  40. // Causing conflicts with 3rd party apps using adodb
  41.  
  42. /**
  43. * phpGACL main class
  44. *
  45. * Class gacl should be used in applications where only querying the phpGACL
  46. * database is required.
  47. *
  48. * @package phpGACL
  49. * @author Mike Benoit <ipso@snappymail.ca>
  50. */
  51. class gacl {
  52.     /*
  53.     --- Private properties ---
  54.     */
  55.     /** @var boolean Enables Debug output if true */
  56.     var $_debug = FALSE;
  57.  
  58.     /**
  59.      * Joomla usage
  60.      */
  61.     var $_debugLog = null;
  62.  
  63.     /*
  64.     --- Database configuration. ---
  65.     */
  66.     /** @var string Prefix for all the phpgacl tables in the database */
  67.     var $_db_table_prefix = '';
  68.  
  69.     /** @var string The database type, based on available ADODB connectors - mysql, postgres7, sybase, oci8po See here for more: http://php.weblogs.com/adodb_manual#driverguide */
  70.     var $_db_type = 'mysql';
  71.  
  72.     /** @var string The database server */
  73.     var $_db_host = 'localhost';
  74.  
  75.     /** @var string The database user name */
  76.     var $_db_user = 'root';
  77.  
  78.     /** @var string The database user password */
  79.     var $_db_password = '';
  80.  
  81.     /** @var string The database name */
  82.     var $_db_name = 'gacl';
  83.  
  84.     /** @var object An ADODB database connector object */
  85.     var $_db = '';
  86.  
  87.     /*
  88.      * NOTE:     This cache must be manually cleaned each time ACL's are modified.
  89.      *         Alternatively you could wait for the cache to expire.
  90.      */
  91.  
  92.     /** @var boolean Caches queries if true */
  93.     var $_caching = FALSE;
  94.  
  95.     /** @var boolean Force cache to expire */
  96.     var $_force_cache_expire = TRUE;
  97.  
  98.     /** @var string The directory for cache file to eb written (ensure write permission are set) */
  99.     var $_cache_dir = '/tmp/phpgacl_cache'; // NO trailing slash
  100.  
  101.     /** @var int The time for the cache to expire in seconds - 600 == Ten Minutes */
  102.     var $_cache_expire_time=600;
  103.  
  104.     /** @var string A switch to put acl_check into '_group_' mode */
  105.     var $_group_switch = '_group_';
  106.  
  107.     /**
  108.      * Constructor
  109.      * @param array An arry of options to oeverride the class defaults
  110.      */
  111.     function gacl($options = NULL) {
  112.  
  113.         $available_options = array('db','debug','items_per_page','max_select_box_items','max_search_return_items','db_table_prefix','db_type','db_host','db_user','db_password','db_name','caching','force_cache_expire','cache_dir','cache_expire_time');
  114.         if (is_array($options)) {
  115.             foreach ($options as $key => $value) {
  116.                 $this->debug_text("Option: $key");
  117.  
  118.                 if (in_array($key, $available_options) ) {
  119.                     $this->debug_text("Valid Config options: $key");
  120.                     $property = '_'.$key;
  121.                     $this->$property = $value;
  122.                 } else {
  123.                     $this->debug_text("ERROR: Config option: $key is not a valid option");
  124.                 }
  125.             }
  126.         }
  127.  
  128.         //Use NUM for slight performance/memory reasons.
  129.         //Leave this in for backwards compatibility with older ADODB installations.
  130.         //If your using ADODB v3.5+ feel free to comment out the following line if its giving you problems.
  131.         //$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
  132.  
  133.         if (is_object($this->_db)) {
  134.             $this->db = &$this->_db;
  135.         } else {
  136.             require_once( ADODB_DIR .'/adodb.inc.php');
  137.             require_once( ADODB_DIR .'/adodb-pager.inc.php');
  138.  
  139.             $this->db = ADONewConnection($this->_db_type);
  140.             $this->db->SetFetchMode(ADODB_FETCH_NUM);
  141.             $this->db->PConnect($this->_db_host, $this->_db_user, $this->_db_password, $this->_db_name);
  142.         }
  143.         $this->db->debug = $this->_debug;
  144.  
  145.         if ( $this->_caching == TRUE ) {
  146.             if (!class_exists('Hashed_Cache_Lite')) {
  147.                 require_once(dirname(__FILE__) .'/Cache_Lite/Hashed_Cache_Lite.php');
  148.             }
  149.  
  150.             /*
  151.              * Cache options. We default to the highest performance. If you run in to cache corruption problems,
  152.              * Change all the 'false' to 'true', this will slow things down slightly however.
  153.              */
  154.  
  155.             $cache_options = array(
  156.                 'caching' => $this->_caching,
  157.                 'cacheDir' => $this->_cache_dir.'/',
  158.                 'lifeTime' => $this->_cache_expire_time,
  159.                 'fileLocking' => TRUE,
  160.                 'writeControl' => FALSE,
  161.                 'readControl' => FALSE,
  162.                 'memoryCaching' => TRUE,
  163.                 'automaticSerialization' => FALSE
  164.             );
  165.             $this->Cache_Lite = new Hashed_Cache_Lite($cache_options);
  166.         }
  167.  
  168.         return true;
  169.     }
  170.  
  171.     /**
  172.     * Prints debug text if debug is enabled.
  173.     * @param string THe text to output
  174.     * @return boolean Always returns true
  175.     */
  176.     function debug_text($text) {
  177.         if (!$this->_debugLog)
  178.         {
  179.             $this->_debugLog = array();
  180.         }
  181.  
  182.         $this->_debugLog[] = $text;
  183.         if ($this->_debug) {
  184.             echo "$text<br>\n";
  185.         }
  186.  
  187.         return true;
  188.     }
  189.  
  190.     /**
  191.     * Prints database debug text if debug is enabled.
  192.     * @param string The name of the function calling this method
  193.     * @return string Returns an error message
  194.     */
  195.     function debug_db($function_name = '') {
  196.         if ($function_name != '') {
  197.             $function_name .= ' (): ';
  198.         }
  199.  
  200.         return $this->debug_text ($function_name .'database error: '. $this->db->ErrorMsg() .' ('. $this->db->ErrorNo() .')');
  201.     }
  202.  
  203.     /**
  204.     * Wraps the actual acl_query() function.
  205.     *
  206.     * It is simply here to return TRUE/FALSE accordingly.
  207.     * @param string The ACO section value
  208.     * @param string The ACO value
  209.     * @param string The ARO section value
  210.     * @param string The ARO section
  211.     * @param string The AXO section value (optional)
  212.     * @param string The AXO section value (optional)
  213.     * @param integer The group id of the ARO ??Mike?? (optional)
  214.     * @param integer The group id of the AXO ??Mike?? (optional)
  215.     * @return boolean TRUE if the check succeeds, false if not.
  216.     */
  217.     function acl_check($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL, $root_aro_group=NULL, $root_axo_group=NULL) {
  218.         $acl_result = $this->acl_query($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value, $axo_value, $root_aro_group, $root_axo_group);
  219.  
  220.         return $acl_result['allow'];
  221.     }
  222.  
  223.     /**
  224.     * Wraps the actual acl_query() function.
  225.     *
  226.     * Quick access to the return value of an ACL.
  227.     * @param string The ACO section value
  228.     * @param string The ACO value
  229.     * @param string The ARO section value
  230.     * @param string The ARO section
  231.     * @param string The AXO section value (optional)
  232.     * @param string The AXO section value (optional)
  233.     * @param integer The group id of the ARO (optional)
  234.     * @param integer The group id of the AXO (optional)
  235.     * @return string The return value of the ACL
  236.     */
  237.     function acl_return_value($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL, $root_aro_group=NULL, $root_axo_group=NULL) {
  238.         $acl_result = $this->acl_query($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value, $axo_value, $root_aro_group, $root_axo_group);
  239.  
  240.         return $acl_result['return_value'];
  241.     }
  242.  
  243.     /**
  244.      * Handles ACL lookups over arrays of AROs
  245.      * @param string The ACO section value
  246.      * @param string The ACO value
  247.     * @param array An named array of arrays, each element in the format aro_section_value=>array(aro_value1,aro_value1,...)
  248.      * @return mixed The same data format as inputted.
  249.      */
  250.     function acl_check_array($aco_section_value, $aco_value, $aro_array) {
  251.         /*
  252.             Input Array:
  253.                 Section => array(Value, Value, Value),
  254.                 Section => array(Value, Value, Value)
  255.  
  256.          */
  257.  
  258.         if (!is_array($aro_array)) {
  259.             $this->debug_text("acl_query_array(): ARO Array must be passed");
  260.             return false;
  261.         }
  262.  
  263.         foreach($aro_array as $aro_section_value => $aro_value_array) {
  264.             foreach ($aro_value_array as $aro_value) {
  265.                 $this->debug_text("acl_query_array(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
  266.  
  267.                 if( $this->acl_check($aco_section_value, $aco_value, $aro_section_value, $aro_value) ) {
  268.                     $this->debug_text("acl_query_array(): ACL_CHECK True");
  269.                     $retarr[$aro_section_value][] = $aro_value;
  270.                 } else {
  271.                     $this->debug_text("acl_query_array(): ACL_CHECK False");
  272.                 }
  273.             }
  274.         }
  275.  
  276.         return $retarr;
  277.  
  278.     }
  279.  
  280.     /**
  281.     * The Main function that does the actual ACL lookup.
  282.     * @param string The ACO section value
  283.     * @param string The ACO value
  284.     * @param string The ARO section value
  285.     * @param string The ARO section
  286.     * @param string The AXO section value (optional)
  287.     * @param string The AXO section value (optional)
  288.     * @param string The value of the ARO group (optional)
  289.     * @param string The value of the AXO group (optional)
  290.     * @param boolean Debug the operation if true (optional)
  291.     * @return array Returns as much information as possible about the ACL so other functions can trim it down and omit unwanted data.
  292.     */
  293.     function acl_query($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL, $root_aro_group=NULL, $root_axo_group=NULL, $debug=NULL) {
  294.  
  295.         $cache_id = 'acl_query_'.$aco_section_value.'-'.$aco_value.'-'.$aro_section_value.'-'.$aro_value.'-'.$axo_section_value.'-'.$axo_value.'-'.$root_aro_group.'-'.$root_axo_group.'-'.$debug;
  296.  
  297.         $retarr = $this->get_cache($cache_id);
  298.  
  299.         if (!$retarr) {
  300.             /*
  301.              * Grab all groups mapped to this ARO/AXO
  302.              */
  303.             $aro_group_ids = $this->acl_get_groups($aro_section_value, $aro_value, $root_aro_group, 'ARO');
  304.  
  305.             if (is_array($aro_group_ids) AND !empty($aro_group_ids)) {
  306.                 $sql_aro_group_ids = implode(',', $aro_group_ids);
  307.             }
  308.  
  309.             if ($axo_section_value !== '' AND $axo_value !== '') {
  310.                 $axo_group_ids = $this->acl_get_groups($axo_section_value, $axo_value, $root_axo_group, 'AXO');
  311.  
  312.                 if (is_array($axo_group_ids) AND !empty($axo_group_ids)) {
  313.                     $sql_axo_group_ids = implode(',', $axo_group_ids);
  314.                 }
  315.             }
  316.  
  317.             /*
  318.              * This query is where all the magic happens.
  319.              * The ordering is very important here, as well very tricky to get correct.
  320.              * Currently there can be  duplicate ACLs, or ones that step on each other toes. In this case, the ACL that was last updated/created
  321.              * is used.
  322.              *
  323.              * This is probably where the most optimizations can be made.
  324.              */
  325.  
  326.             $order_by = array();
  327.  
  328.             $query = '
  329.                     SELECT        a.id,a.allow,a.return_value
  330.                     FROM        '. $this->_db_table_prefix .'acl a
  331.                     LEFT JOIN     '. $this->_db_table_prefix .'aco_map ac ON ac.acl_id=a.id';
  332.  
  333.             if ($aro_section_value != $this->_group_switch) {
  334.                 $query .= '
  335.                     LEFT JOIN    '. $this->_db_table_prefix .'aro_map ar ON ar.acl_id=a.id';
  336.             }
  337.  
  338.             if ($axo_section_value != $this->_group_switch) {
  339.                 $query .= '
  340.                     LEFT JOIN    '. $this->_db_table_prefix .'axo_map ax ON ax.acl_id=a.id';
  341.             }
  342.  
  343.             /*
  344.              * if there are no aro groups, don't bother doing the join.
  345.              */
  346.             if (isset($sql_aro_group_ids)) {
  347.                 $query .= '
  348.                     LEFT JOIN    '. $this->_db_table_prefix .'aro_groups_map arg ON arg.acl_id=a.id
  349.                     LEFT JOIN    '. $this->_db_table_prefix .'aro_groups rg ON rg.id=arg.group_id';
  350.             }
  351.  
  352.             // this join is necessary to weed out rules associated with axo groups
  353.             $query .= '
  354.                     LEFT JOIN    '. $this->_db_table_prefix .'axo_groups_map axg ON axg.acl_id=a.id';
  355.  
  356.             /*
  357.              * if there are no axo groups, don't bother doing the join.
  358.              * it is only used to rank by the level of the group.
  359.              */
  360.             if (isset($sql_axo_group_ids)) {
  361.                 $query .= '
  362.                     LEFT JOIN    '. $this->_db_table_prefix .'axo_groups xg ON xg.id=axg.group_id';
  363.             }
  364.  
  365.             //Move the below line to the LEFT JOIN above for PostgreSQL's sake.
  366.             //AND    ac.acl_id=a.id
  367.             $query .= '
  368.                     WHERE        a.enabled=1
  369.                         AND        (ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value='. $this->db->quote($aco_value) .')';
  370.  
  371.             // if we are querying an aro group
  372.             if ($aro_section_value == $this->_group_switch) {
  373.                 // if acl_get_groups did not return an array
  374.                 if ( !isset ($sql_aro_group_ids) ) {
  375.                     $this->debug_text ('acl_query(): Invalid ARO Group: '. $aro_value);
  376.                     return FALSE;
  377.                 }
  378.  
  379.                 $query .= '
  380.                         AND        rg.id IN ('. $sql_aro_group_ids .')';
  381.  
  382.                 $order_by[] = '(rg.rgt-rg.lft) ASC';
  383.             } else {
  384.                 $query .= '
  385.                         AND        ((ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value='. $this->db->quote($aro_value) .')';
  386.  
  387.                 if ( isset ($sql_aro_group_ids) ) {
  388.                     $query .= ' OR rg.id IN ('. $sql_aro_group_ids .')';
  389.  
  390.                     $order_by[] = '(CASE WHEN ar.value IS NULL THEN 0 ELSE 1 END) DESC';
  391.                     $order_by[] = '(rg.rgt-rg.lft) ASC';
  392.                 }
  393.  
  394.                 $query .= ')';
  395.             }
  396.  
  397.  
  398.             // if we are querying an axo group
  399.             if ($axo_section_value == $this->_group_switch) {
  400.                 // if acl_get_groups did not return an array
  401.                 if ( !isset ($sql_axo_group_ids) ) {
  402.                     $this->debug_text ('acl_query(): Invalid AXO Group: '. $axo_value);
  403.                     return FALSE;
  404.                 }
  405.  
  406.                 $query .= '
  407.                         AND        xg.id IN ('. $sql_axo_group_ids .')';
  408.  
  409.                 $order_by[] = '(xg.rgt-xg.lft) ASC';
  410.             } else {
  411.                 $query .= '
  412.                         AND        (';
  413.  
  414.                 if ($axo_section_value == '' AND $axo_value == '') {
  415.                     $query .= '(ax.section_value IS NULL AND ax.value IS NULL)';
  416.                 } else {
  417.                     $query .= '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value='. $this->db->quote($axo_value) .')';
  418.                 }
  419.  
  420.                 if (isset($sql_axo_group_ids)) {
  421.                     $query .= ' OR xg.id IN ('. $sql_axo_group_ids .')';
  422.  
  423.                     $order_by[] = '(CASE WHEN ax.value IS NULL THEN 0 ELSE 1 END) DESC';
  424.                     $order_by[] = '(xg.rgt-xg.lft) ASC';
  425.                 } else {
  426.                     $query .= ' AND axg.group_id IS NULL';
  427.                 }
  428.  
  429.                 $query .= ')';
  430.             }
  431.  
  432.             /*
  433.              * The ordering is always very tricky and makes all the difference in the world.
  434.              * Order (ar.value IS NOT NULL) DESC should put ACLs given to specific AROs
  435.              * ahead of any ACLs given to groups. This works well for exceptions to groups.
  436.              */
  437.  
  438.             $order_by[] = 'a.updated_date DESC';
  439.  
  440.             $query .= '
  441.                     ORDER BY    '. implode (',', $order_by) . '
  442.                     ';
  443.  
  444.             // we are only interested in the first row
  445.             $rs = $this->db->SelectLimit($query, 1);
  446.  
  447.             if (!is_object($rs)) {
  448.                 $this->debug_db('acl_query');
  449.                 return FALSE;
  450.             }
  451.  
  452.             $row =& $rs->FetchRow();
  453.  
  454.             /*
  455.              * Return ACL ID. This is the key to "hooking" extras like pricing assigned to ACLs etc... Very useful.
  456.              */
  457.             if (is_array($row)) {
  458.                 // Permission granted?
  459.                 // This below oneliner is very confusing.
  460.                 //$allow = (isset($row[1]) AND $row[1] == 1);
  461.  
  462.                 //Prefer this.
  463.                 if ( isset($row[1]) AND $row[1] == 1 ) {
  464.                     $allow = TRUE;
  465.                 } else {
  466.                     $allow = FALSE;
  467.                 }
  468.  
  469.                 $retarr = array('acl_id' => &$row[0], 'return_value' => &$row[2], 'allow' => $allow);
  470.             } else {
  471.                 // Permission denied.
  472.                 $retarr = array('acl_id' => NULL, 'return_value' => NULL, 'allow' => FALSE);
  473.             }
  474.  
  475.             /*
  476.              * Return the query that we ran if in debug mode.
  477.              */
  478.             if ($debug == TRUE) {
  479.                 $retarr['query'] = &$query;
  480.             }
  481.  
  482.             //Cache data.
  483.             $this->put_cache($retarr, $cache_id);
  484.         }
  485.  
  486.         $this->debug_text("<b>acl_query():</b> ACO Section: $aco_section_value ACO Value: $aco_value ARO Section: $aro_section_value ARO Value $aro_value ACL ID: ". $retarr['acl_id'] .' Result: '. $retarr['allow']);
  487.         return $retarr;
  488.     }
  489.  
  490.     /**
  491.     * Grabs all groups mapped to an ARO. You can also specify a root_group for subtree'ing.
  492.     * @param string The section value or the ARO or ACO
  493.     * @param string The value of the ARO or ACO
  494.     * @param integer The group id of the group to start at (optional)
  495.     * @param string The type of group, either ARO or AXO (optional)
  496.     */
  497.     function acl_get_groups($section_value, $value, $root_group=NULL, $group_type='ARO') {
  498.  
  499.         switch(strtolower($group_type)) {
  500.             case 'axo':
  501.                 $group_type = 'axo';
  502.                 $object_table = $this->_db_table_prefix .'axo';
  503.                 $group_table = $this->_db_table_prefix .'axo_groups';
  504.                 $group_map_table = $this->_db_table_prefix .'groups_axo_map';
  505.                 break;
  506.             default:
  507.                 $group_type = 'aro';
  508.                 $object_table = $this->_db_table_prefix .'aro';
  509.                 $group_table = $this->_db_table_prefix .'aro_groups';
  510.                 $group_map_table = $this->_db_table_prefix .'groups_aro_map';
  511.                 break;
  512.         }
  513.  
  514.         //$profiler->startTimer( "acl_get_groups()");
  515.  
  516.         //Generate unique cache id.
  517.         $cache_id = 'acl_get_groups_'.$section_value.'-'.$value.'-'.$root_group.'-'.$group_type;
  518.  
  519.         $retarr = $this->get_cache($cache_id);
  520.  
  521.         if (!$retarr) {
  522.  
  523.             // Make sure we get the groups
  524.             $query = '
  525.                     SELECT         DISTINCT g2.id';
  526.  
  527.             if ($section_value == $this->_group_switch) {
  528.                 $query .= '
  529.                     FROM        ' . $group_table . ' g1,' . $group_table . ' g2';
  530.  
  531.                 $where = '
  532.                     WHERE        g1.value=' . $this->db->quote( $value );
  533.             } else {
  534.                 $query .= '
  535.                     FROM        '. $object_table .' o,'. $group_map_table .' gm,'. $group_table .' g1,'. $group_table .' g2';
  536.  
  537.                 $where = '
  538.                     WHERE        (o.section_value='. $this->db->quote($section_value) .' AND o.value='. $this->db->quote($value) .')
  539.                         AND        gm.'. $group_type .'_id=o.id
  540.                         AND        g1.id=gm.group_id';
  541.             }
  542.  
  543.             /*
  544.              * If root_group_id is specified, we have to narrow this query down
  545.              * to just groups deeper in the tree then what is specified.
  546.              * This essentially creates a virtual "subtree" and ignores all outside groups.
  547.              * Useful for sites like sourceforge where you may seperate groups by "project".
  548.              */
  549.             if ( $root_group != '') {
  550.                 //It is important to note the below line modifies the tables being selected.
  551.                 //This is the reason for the WHERE variable.
  552.                 $query .= ','. $group_table .' g3';
  553.  
  554.                 $where .= '
  555.                         AND        g3.value='. $this->db->quote( $root_group ) .'
  556.                         AND        ((g2.lft BETWEEN g3.lft AND g1.lft) AND (g2.rgt BETWEEN g1.rgt AND g3.rgt))';
  557.             } else {
  558.                 $where .= '
  559.                         AND        (g2.lft <= g1.lft AND g2.rgt >= g1.rgt)';
  560.             }
  561.  
  562.             $query .= $where;
  563.  
  564.             // $this->debug_text($query);
  565.             $rs = $this->db->Execute($query);
  566.  
  567.             if (!is_object($rs)) {
  568.                 $this->debug_db('acl_get_groups');
  569.                 return FALSE;
  570.             }
  571.  
  572.             $retarr = array();
  573.  
  574.             /*
  575.              * Changed by: Louis Landry for Joomla ACL integration
  576.              * 21-Jan-2006
  577.              */
  578.             for ($i = 0; $i < count($rs->data); $i++) {
  579.                 //$retarr[] = $rs->data[$i]['id'];
  580.                 $retarr[] = reset( $rs->data[$i] );
  581.             }
  582.  
  583.             //Cache data.
  584.             $this->put_cache($retarr, $cache_id);
  585.         }
  586.  
  587.         return $retarr;
  588.     }
  589.  
  590.     /**
  591.     * Uses PEAR's Cache_Lite package to grab cached arrays, objects, variables etc...
  592.     * using unserialize() so it can handle more then just text string.
  593.     * @param string The id of the cached object
  594.     * @return mixed The cached object, otherwise FALSE if the object identifier was not found
  595.     */
  596.     function get_cache($cache_id) {
  597.  
  598.         if ( $this->_caching == TRUE ) {
  599.             $this->debug_text("get_cache(): on ID: $cache_id");
  600.  
  601.             if ( is_string($this->Cache_Lite->get($cache_id) ) ) {
  602.                 return unserialize($this->Cache_Lite->get($cache_id) );
  603.             }
  604.         }
  605.  
  606.         return false;
  607.     }
  608.  
  609.     /**
  610.     * Uses PEAR's Cache_Lite package to write cached arrays, objects, variables etc...
  611.     * using serialize() so it can handle more then just text string.
  612.     * @param mixed A variable to cache
  613.     * @param string The id of the cached variable
  614.     */
  615.     function put_cache($data, $cache_id) {
  616.  
  617.         if ( $this->_caching == TRUE ) {
  618.             $this->debug_text("put_cache(): Cache MISS on ID: $cache_id");
  619.  
  620.             return $this->Cache_Lite->save(serialize($data), $cache_id);
  621.         }
  622.  
  623.         return false;
  624.     }
  625. }
  626. ?>
  627.